<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body></body>

  <script>
    // ==================== 手写深拷贝 ====================
    function deepClone(obj, map = new WeakMap()) {
      if (obj === null || typeof obj !== "object") return obj
      if (obj instanceof Date) return new Date(obj)
      if (obj instanceof Array) return obj.map((item) => deepClone(item))
      if (typeof obj === "object") {
        const clonedObj = {}
        for (let key in obj) {
          if (obj.hasOwnProperty(key)) {
            clonedObj[key] = deepClone(obj[key])
          }
        }
        return clonedObj
      }
    }

    // 示例
    const original = { a: 1, b: { c: 2, d: [3, 4] } }
    const cloned = deepClone(original)
    console.log("深拷贝示例:", cloned)

    // ==================== 手写 getType 函数 ====================
    function getType(value) {
      return Object.prototype.toString.call(value).slice(8, -1).toLowerCase()
    }

    // 示例
    console.log("getType示例:")
    console.log(getType(123)) // number
    console.log(getType("hello")) // string
    console.log(getType([])) // array
    console.log(getType({})) // object
    console.log(getType(null)) // null

    // ==================== 手写 class 继承 ====================
    class Animal {
      constructor(name) {
        this.name = name
      }

      speak() {
        console.log(`${this.name} makes a sound`)
      }
    }

    class Dog extends Animal {
      constructor(name, breed) {
        super(name)
        this.breed = breed
      }

      speak() {
        console.log(`${this.name} barks`)
      }
    }

    // 示例
    const dog = new Dog("旺财", "金毛")
    dog.speak() // 旺财 barks

    // ==================== 手写防抖 Debounce ====================
    function debounce(func, delay) {
      let timeoutId
      return function (...args) {
        clearTimeout(timeoutId)
        timeoutId = setTimeout(() => func.apply(this, args), delay)
      }
    }

    // 示例
    const debouncedLog = debounce(() => console.log("防抖执行"), 1000)

    // ==================== 手写截流 Throttle ====================
    function throttle(func, delay) {
      let lastTime = 0
      return function (...args) {
        const now = Date.now()
        if (now - lastTime >= delay) {
          lastTime = now
          func.apply(this, args)
        }
      }
    }

    // 示例
    const throttledLog = throttle(() => console.log("节流执行"), 1000)

    // ==================== 手写 bind ====================
    Function.prototype.myBind = function (context, ...args) {
      const fn = this
      return function (...newArgs) {
        return fn.apply(context, [...args, ...newArgs])
      }
    }

    // 示例
    function greet(greeting, punctuation) {
      return `${greeting} ${this.name}${punctuation}`
    }
    const person = { name: "张三" }
    const boundGreet = greet.myBind(person, "你好")
    console.log("bind示例:", boundGreet("!"))

    // ==================== 手写 call 和 apply ====================
    Function.prototype.myCall = function (context, ...args) {
      context = context || window
      const fnSymbol = Symbol()
      context[fnSymbol] = this
      const result = context[fnSymbol](...args)
      delete context[fnSymbol]
      return result
    }

    Function.prototype.myApply = function (context, args) {
      context = context || window
      const fnSymbol = Symbol()
      context[fnSymbol] = this
      const result = context[fnSymbol](...(args || []))
      delete context[fnSymbol]
      return result
    }

    // 示例
    console.log("call示例:", greet.myCall(person, "你好", "!"))

    // ==================== 手写 EventBus 自定义事件 ====================
    class EventBus {
      constructor() {
        this.events = {}
      }

      on(event, callback) {
        if (!this.events[event]) {
          this.events[event] = []
        }
        this.events[event].push(callback)
      }

      emit(event, ...args) {
        if (this.events[event]) {
          this.events[event].forEach((callback) => callback(...args))
        }
      }

      off(event, callback) {
        if (this.events[event]) {
          this.events[event] = this.events[event].filter(
            (cb) => cb !== callback
          )
        }
      }
    }

    // 示例
    const eventBus = new EventBus()
    eventBus.on("test", (data) => console.log("EventBus示例:", data))
    eventBus.emit("test", "Hello EventBus")

    // ==================== 手写数组拍平 Array Flatten ====================
    function flatten(arr) {
      return arr.reduce((acc, val) => {
        return acc.concat(Array.isArray(val) ? flatten(val) : val)
      }, [])
    }

    // 示例
    const nestedArray = [1, [2, 3], [4, [5, 6]]]
    console.log("数组拍平示例:", flatten(nestedArray))

    // ==================== 手写解析 URL 参数为 JS 对象 ====================
    function parseURL(url) {
      const params = {}
      const queryString = url.split("?")[1]
      if (queryString) {
        queryString.split("&").forEach((param) => {
          const [key, value] = param.split("=")
          params[decodeURIComponent(key)] = decodeURIComponent(value || "")
        })
      }
      return params
    }

    // 示例
    const url = "https://example.com?name=张三&age=25&city=北京"
    console.log("URL解析示例:", parseURL(url))

    // ==================== 手写数组去重 ====================
    function uniqueArray(arr) {
      return [...new Set(arr)]
    }

    function uniqueArrayAdvanced(arr) {
      const seen = new Map()
      return arr.filter((item) => {
        const key = typeof item + JSON.stringify(item)
        if (seen.has(key)) {
          return false
        }
        seen.set(key, true)
        return true
      })
    }

    // 示例
    const duplicateArray = [1, 2, 2, 3, 3, 4]
    console.log("数组去重示例:", uniqueArray(duplicateArray))

    // ==================== 手写红绿灯 ====================
    function trafficLight() {
      const lights = ["红灯", "绿灯", "黄灯"]
      const durations = [3000, 2000, 1000]
      let currentIndex = 0

      function switchLight() {
        console.log(`当前是: ${lights[currentIndex]}`)
        setTimeout(() => {
          currentIndex = (currentIndex + 1) % lights.length
          switchLight()
        }, durations[currentIndex])
      }

      switchLight()
    }

    // 示例（注释掉避免无限循环）
    // trafficLight();

    // ==================== 手写 Promise ====================
    class MyPromise {
      constructor(executor) {
        this.state = "pending"
        this.value = undefined
        this.reason = undefined
        this.onFulfilledCallbacks = []
        this.onRejectedCallbacks = []

        const resolve = (value) => {
          if (this.state === "pending") {
            this.state = "fulfilled"
            this.value = value
            this.onFulfilledCallbacks.forEach((fn) => fn())
          }
        }

        const reject = (reason) => {
          if (this.state === "pending") {
            this.state = "rejected"
            this.reason = reason
            this.onRejectedCallbacks.forEach((fn) => fn())
          }
        }

        try {
          executor(resolve, reject)
        } catch (error) {
          reject(error)
        }
      }

      then(onFulfilled, onRejected) {
        return new MyPromise((resolve, reject) => {
          if (this.state === "fulfilled") {
            try {
              const result = onFulfilled ? onFulfilled(this.value) : this.value
              resolve(result)
            } catch (error) {
              reject(error)
            }
          } else if (this.state === "rejected") {
            try {
              const result = onRejected ? onRejected(this.reason) : this.reason
              resolve(result)
            } catch (error) {
              reject(error)
            }
          } else {
            this.onFulfilledCallbacks.push(() => {
              try {
                const result = onFulfilled
                  ? onFulfilled(this.value)
                  : this.value
                resolve(result)
              } catch (error) {
                reject(error)
              }
            })
            this.onRejectedCallbacks.push(() => {
              try {
                const result = onRejected
                  ? onRejected(this.reason)
                  : this.reason
                resolve(result)
              } catch (error) {
                reject(error)
              }
            })
          }
        })
      }
    }

    // 示例
    new MyPromise((resolve) => {
      setTimeout(() => resolve("Promise示例完成"), 1000)
    }).then((result) => console.log(result))

    // ==================== 手写 Promise.all ====================
    MyPromise.all = function (promises) {
      return new MyPromise((resolve, reject) => {
        const results = []
        let completedCount = 0

        promises.forEach((promise, index) => {
          Promise.resolve(promise)
            .then((value) => {
              results[index] = value
              completedCount++
              if (completedCount === promises.length) {
                resolve(results)
              }
            })
            .catch(reject)
        })
      })
    }

    // 示例
    const promises = [
      Promise.resolve(1),
      Promise.resolve(2),
      Promise.resolve(3),
    ]
    MyPromise.all(promises).then((results) =>
      console.log("Promise.all示例:", results)
    )

    // ==================== 手写 Promise.race ====================
    MyPromise.race = function (promises) {
      return new MyPromise((resolve, reject) => {
        promises.forEach((promise) => {
          Promise.resolve(promise).then(resolve).catch(reject)
        })
      })
    }

    // ==================== 手写 Promise.allSettled ====================
    MyPromise.allSettled = function (promises) {
      return new MyPromise((resolve) => {
        const results = []
        let completedCount = 0

        promises.forEach((promise, index) => {
          Promise.resolve(promise)
            .then((value) => {
              results[index] = { status: "fulfilled", value }
            })
            .catch((reason) => {
              results[index] = { status: "rejected", reason }
            })
            .finally(() => {
              completedCount++
              if (completedCount === promises.length) {
                resolve(results)
              }
            })
        })
      })
    }

    // ==================== 手写一个 LazyMan 实现 sleep 机制 ====================
    class LazyMan {
      constructor(name) {
        this.name = name
        this.tasks = []
        console.log(`Hi! This is ${name}!`)
        setTimeout(() => this.next(), 0)
      }

      sleep(time) {
        this.tasks.push(() => {
          setTimeout(() => {
            console.log(`等待了${time}秒...`)
            this.next()
          }, time * 1000)
        })
        return this
      }

      eat(food) {
        this.tasks.push(() => {
          console.log(`Eat ${food}~`)
          this.next()
        })
        return this
      }

      next() {
        const task = this.tasks.shift()
        task && task()
      }
    }

    // 示例
    // new LazyMan('Tony').eat('lunch').sleep(2).eat('dinner');

    // ==================== 手写 curry 函数，实现函数柯里化 ====================
    function curry(fn) {
      return function curried(...args) {
        if (args.length >= fn.length) {
          return fn.apply(this, args)
        } else {
          return function (...nextArgs) {
            return curried.apply(this, args.concat(nextArgs))
          }
        }
      }
    }

    // 示例
    function add(a, b, c) {
      return a + b + c
    }
    const curriedAdd = curry(add)
    console.log("curry示例:", curriedAdd(1)(2)(3))

    // ==================== 手写 compose 函数 ====================
    function compose(...fns) {
      return function (value) {
        return fns.reduceRight((acc, fn) => fn(acc), value)
      }
    }

    // 示例
    const addOne = (x) => x + 1
    const multiplyTwo = (x) => x * 2
    const composed = compose(multiplyTwo, addOne)
    console.log("compose示例:", composed(3)) // (3 + 1) * 2 = 8

    // ==================== 手写一个 LRU 缓存 ====================
    class LRUCache {
      constructor(capacity) {
        this.capacity = capacity
        this.cache = new Map()
      }

      get(key) {
        if (this.cache.has(key)) {
          const value = this.cache.get(key)
          this.cache.delete(key)
          this.cache.set(key, value)
          return value
        }
        return -1
      }

      put(key, value) {
        if (this.cache.has(key)) {
          this.cache.delete(key)
        } else if (this.cache.size >= this.capacity) {
          const firstKey = this.cache.keys().next().value
          this.cache.delete(firstKey)
        }
        this.cache.set(key, value)
      }
    }

    // 示例
    const lru = new LRUCache(2)
    lru.put(1, "one")
    lru.put(2, "two")
    console.log("LRU示例:", lru.get(1)) // 'one'

    // ==================== 使用 Vue3 Composable 组合式函数，实现 useCount ====================
    // 注意：这需要在Vue3环境中运行
    /*
    function useCount(initialValue = 0) {
      const count = ref(initialValue);
      
      const increment = () => count.value++;
      const decrement = () => count.value--;
      const reset = () => count.value = initialValue;
      
      return {
        count: readonly(count),
        increment,
        decrement,
        reset
      };
    }
    */

    // ==================== 使用 Vue3 Composable 组合式函数，实现 useRequest ====================
    // 注意：这需要在Vue3环境中运行
    /*
    function useRequest(url) {
      const data = ref(null);
      const loading = ref(false);
      const error = ref(null);
      
      const execute = async () => {
        loading.value = true;
        error.value = null;
        try {
          const response = await fetch(url);
          data.value = await response.json();
        } catch (err) {
          error.value = err;
        } finally {
          loading.value = false;
        }
      };
      
      return {
        data: readonly(data),
        loading: readonly(loading),
        error: readonly(error),
        execute
      };
    }
    */

    // ==================== 使用 React Hook 实现 useCount ====================
    // 注意：这需要在React环境中运行
    /*
    function useCount(initialValue = 0) {
      const [count, setCount] = useState(initialValue);
      
      const increment = useCallback(() => setCount(c => c + 1), []);
      const decrement = useCallback(() => setCount(c => c - 1), []);
      const reset = useCallback(() => setCount(initialValue), [initialValue]);
      
      return { count, increment, decrement, reset };
    }
    */

    // ==================== 使用 React Hook 实现 useRequest ====================
    // 注意：这需要在React环境中运行
    /*
    function useRequest(url) {
      const [data, setData] = useState(null);
      const [loading, setLoading] = useState(false);
      const [error, setError] = useState(null);
      
      const execute = useCallback(async () => {
        setLoading(true);
        setError(null);
        try {
          const response = await fetch(url);
          const result = await response.json();
          setData(result);
        } catch (err) {
          setError(err);
        } finally {
          setLoading(false);
        }
      }, [url]);
      
      return { data, loading, error, execute };
    }
    */

    // ==================== 手写 VNode 对象，表示 DOM 节点 ====================
    class VNode {
      constructor(tag, props = {}, children = []) {
        this.tag = tag
        this.props = props
        this.children = children
      }

      render() {
        const element = document.createElement(this.tag)

        // 设置属性
        Object.keys(this.props).forEach((key) => {
          if (key.startsWith("on")) {
            const event = key.slice(2).toLowerCase()
            element.addEventListener(event, this.props[key])
          } else {
            element.setAttribute(key, this.props[key])
          }
        })

        // 添加子节点
        this.children.forEach((child) => {
          if (typeof child === "string") {
            element.appendChild(document.createTextNode(child))
          } else if (child instanceof VNode) {
            element.appendChild(child.render())
          }
        })

        return element
      }
    }

    // 示例
    const vnode = new VNode("div", { class: "container" }, [
      new VNode("h1", {}, ["Hello VNode"]),
      new VNode("p", {}, ["这是一个段落"]),
    ])
    console.log("VNode示例:", vnode)

    console.log("所有示例代码已加载完成！")
  </script>
</html>
